# coding:utf-8
from typing import Union, Callable, Any, Optional

from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QIcon, QResizeEvent
from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLayout
from qfluentwidgets import BodyLabel, setFont, FlowLayout, FluentIconBase, InfoBar, StateToolTip, \
    TransparentToolButton, FluentIcon as FIF, ScrollArea, VBoxLayout

from common import FuncThread, FuncSignalData
from ..cards import SampleCard


class ThreadObjectBase:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._stateToolTip = StateToolTip('加载中', '正在运行自定义函数，请稍候...', self)

        self.funcThread = FuncThread(self)

        self.funcThread.funcSignal.connect(self.__onFuncSignal)
        self.funcThread.logSignal.connect(self.onLogSignal)
        self.funcThread.started.connect(self.onThreadStarted)
        self.funcThread.finished.connect(self.onThreadFinished)

        self._stateToolTip.setVisible(False)

    def __onFuncSignal(self, data: FuncSignalData):
        if data.success:
            self.onFuncSuccess(data.result)
        else:
            self.onFuncFailed(data.message)

    def onLogSignal(self, message: str):
        pass

    def onFuncSuccess(self, result: Any):
        pass

    def onFuncFailed(self, message: str):
        InfoBar.error('错误', message, duration=3000, parent=self)

    def onThreadStarted(self):
        self._stateToolTip.setVisible(True)

    def onThreadFinished(self):
        self._stateToolTip.setVisible(False)

    def load(self, func: Callable, *args, **kwargs):
        self.funcThread.setFunc(func, *args, **kwargs)

    def setToolTipTitle(self, title: str):
        self._stateToolTip.setTitle(title)

    def setToolTipContent(self, content: str):
        self._stateToolTip.setContent(content)


class BaseScrollArea(ScrollArea, ThreadObjectBase):
    returned = pyqtSignal(bool)

    title = '插件名称'
    description = '插件描述'
    is_shortcut = True
    object_name = 'BaseScrollArea'
    icon = FIF.APPLICATION

    def __init__(self, parent: QWidget, layout: Callable = VBoxLayout):
        super().__init__(parent)
        self.returnBtn = TransparentToolButton(FIF.RETURN, self)
        self.scrollAreaWidget = QWidget(self)
        self.scrollLayout: VBoxLayout = layout(self.scrollAreaWidget)
        self.scrollLayout.setParent(self.scrollAreaWidget)

        self.setObjectName(self.object_name)
        self.setWidget(self.scrollAreaWidget)
        self.setWidgetResizable(True)
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        self.scrollAreaWidget.setAutoFillBackground(False)
        self.enableTransparentBackground()

        self.returnBtn.setFixedSize(40, 40)
        self.returnBtn.move(36, 20)
        self.returnBtn.clicked.connect(self.returned)

        self.scrollLayout.setAlignment(Qt.AlignmentFlag.AlignTop)
        self.scrollLayout.setContentsMargins(36, 10, 36, 10)
        self.setViewportMargins(0, 0, 10, 0)
        self.setReturnVisible(False)
        self.setToolTipTitle(self.title)

    def setReturnVisible(self, visible: bool):
        self.returnBtn.setVisible(visible)

        if visible:
            self.setViewportMargins(0, 60, 10, 0)
        else:
            self.setViewportMargins(0, 0, 10, 0)

    def resizeEvent(self, event: QResizeEvent):
        self._stateToolTip.move(self.width() - self._stateToolTip.width() - 10, 10)
        super().resizeEvent(event)


class BaseWidget(QWidget, ThreadObjectBase):
    def __init__(self, parent: QWidget):
        super().__init__(parent)
        self._verticalLayout = QVBoxLayout(self)
        self._topWidget = QWidget(self)
        self.topLayout = QVBoxLayout(self._topWidget)
        self.scrollArea = ScrollArea(self)

        self._verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.topLayout.setContentsMargins(36, 20, 36, 20)
        self._verticalLayout.setSpacing(0)
        self._verticalLayout.addWidget(self._topWidget)
        self._verticalLayout.addWidget(self.scrollArea)
        self.scrollArea.enableTransparentBackground()

    def setWidget(self, widget: QWidget):
        self.scrollArea.setWidget(widget)
        self.scrollArea.setWidgetResizable(True)
        self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
        widget.setAutoFillBackground(False)
        self.scrollArea.enableTransparentBackground()

    def setTopVisible(self, visible: bool):
        self._topWidget.setVisible(visible)
        if visible:
            self._verticalLayout.removeWidget(self._topWidget)
            self._topWidget.close()
            self._topWidget.deleteLater()
            del self._topWidget
            self._topWidget = None

    def resizeEvent(self, event: QResizeEvent):
        self._stateToolTip.move(self.width() - self._stateToolTip.width() - 10, 10)
        super().resizeEvent(event)


class FlowTiTleBaseWidget(BaseWidget):
    def __init__(self, title: str, content: str = None, parent: QWidget = None):
        super().__init__(parent)
        self.titleLabel = BodyLabel(title, self)
        self.contentLabel = BodyLabel(self)
        self.scrollAreaWidget = QWidget(self)
        self.flowLayout = FlowLayout(self.scrollAreaWidget)

        self.__initWidgets()
        self.setContent(content)

    def __initWidgets(self):
        setFont(self.titleLabel, 24)
        self.setWidget(self.scrollAreaWidget)

        self.topLayout.addWidget(self.titleLabel)
        self.topLayout.addWidget(self.contentLabel)
        self.flowLayout.setContentsMargins(36, 20, 36, 0)
        self.flowLayout.setHorizontalSpacing(10)
        self.flowLayout.setVerticalSpacing(10)

    def setTitle(self, title: str):
        self.titleLabel.setText(title)

    def setContent(self, content: str):
        if content:
            self.contentLabel.setVisible(True)
            self.contentLabel.setText(content)
        else:
            self.contentLabel.setVisible(False)

    def addSampleCard(self, icon: Union[str, QIcon, FluentIconBase], title: str, content: str,
                      routeKey: str, clicked: Callable = None):
        """ 添加样品卡 """
        card = SampleCard(icon, title, content, routeKey, self)
        if clicked:
            card.clicked.connect(lambda: clicked(routeKey))
        self.flowLayout.addWidget(card)
        return card

    def removeSampleCard(self, routeKey: str):
        """ 移除样品卡 """
        widget = self.findChild(SampleCard, routeKey)
        if widget:
            self.flowLayout.removeWidget(widget)
            widget.close()
            widget.deleteLater()
            del widget
